package com.xxx.redislock.utils;

import org.joda.time.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * JodaTime日期时间工具类
 */
public class JodaUtil {
	
	/******************常用的日期和时间格式，缺少的可以自行添加*************************/
	public static final String DATETIME_PATTERN_DEFAULT = "yyyy-MM-dd HH:mm:ss";
	public static final String DATE_PATTERN_DEFAULT = "yyyy-MM-dd";
	public static final String TIME_PATTERN_DEFAULT = "HH:mm:ss";
	public static final String DATE_PATTERN_YYYYMMDD = "yyyyMMdd";
	public static final String DATETIME_PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
	public static final String DATETIME_PATTERN_YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
	
	// 私有构造方法，防止被实例化
	private JodaUtil() {
		
	}

	/****************** 创建日期时间对象 start ************************/
	/**
	 * 创建当前日期对象（不带参数）
	 * @return
	 */
	public static DateTime now() {
		return new DateTime();
	}
	
	/**
	 * 获得今天零时零分零秒
	 * @return
	 */
	public static DateTime get0OclockOfToday() {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		Date date = calendar.getTime();
		return new DateTime(date);
	}
	
	/**
	 * 创建指定的日期对象（带参数）
	 * @param year
	 * @param monthOfYear
	 * @param dayOfMonth
	 * @param hourOfDay
	 * @param minuteOfHour
	 * @param secondOfMinute
	 * @return
	 */
	public static DateTime getDateTime(int year,
					            	   int monthOfYear,
					            	   int dayOfMonth,
					            	   int hourOfDay,
					            	   int minuteOfHour,
					            	   int secondOfMinute) {
		return new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute);
	}
	
	/**
	 * 创建一个本地日期，只需要年、月、日（不带时、分、秒、毫秒）
	 * @param year
	 * @param monthOfYear
	 * @param dayOfMonth
	 * @return
	 */
	public static LocalDate getDate(int year,
            				 		int monthOfYear,
            				 		int dayOfMonth) {
		return new LocalDate(year, monthOfYear, dayOfMonth);
	}
	
	/**
	 * 创建一个本地时间，只需要时、分、秒、毫秒（不带年、月、日）
	 * @param hourOfDay
	 * @param minuteOfHour
	 * @param secondOfMinute
	 * @param millisOfSecond
	 * @return
	 */
	public static LocalTime getTime(int hourOfDay,
            				 		int minuteOfHour,
            				 		int secondOfMinute,
            				 		int millisOfSecond) {
		return new LocalTime(hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);
	}
	/****************** 创建日期时间对象 end ************************/

	/****************** 日期加减 start ************************/
	/**
	 * 日期加减主要利用以下几个方法：
	 * 	minusDays()/minusMonths()/minusYears()
	 *  plusDays()/plusMonths()/plusYears()
	 */
	/**
	 * 获取昨天的日期
	 */
	public static DateTime yesterday() {
		return someDaysAgo(new DateTime(), 1);
	}
	
	/**
	 * 获取n天前的日期
	 * @param dateTime
	 * @param n
	 * @return
	 */
	public static DateTime someDaysAgo(DateTime dateTime, int n) {
		return dateTime.minusDays(n);
	}
	
	/**
	 * 获取明天的日期
	 * @return
	 */
	public static DateTime tomorrow() {
		return someDaysAfter(new DateTime(), 1);
	}
	
	/**
	 * 获取指定时间seconds秒后的时间
	 * @param dateTime
	 * @param seconds
	 * @return
	 */
	public static DateTime someSecondsAfter(DateTime dateTime, int seconds) {
		return dateTime.plusSeconds(seconds);
	}
	
	/**
	 * 获取指定时间seconds秒前的时间
	 * @param dateTime
	 * @param seconds
	 * @return
	 */
	public static DateTime someSecondsBefore(DateTime dateTime, int seconds) {
		return dateTime.minusSeconds(seconds);
	}
	
	/**
	 * 获取指定日期days天后的日期
	 * @param dateTime
	 * @param days
	 * @return
	 */
	public static DateTime someDaysAfter(DateTime dateTime, int days) {
		return dateTime.plusDays(days);
	}
	
	/**
	 * 获取上个月的日期
	 * @return
	 */
	public static DateTime lastMonth() {
		return someMonthsAgo(new DateTime(), 1);
	}
	
	/**
	 * 获取指定日期months个月之前的日期
	 * @param dateTime
	 * @param months
	 * @return
	 */
	public static DateTime someMonthsAgo(DateTime dateTime, int months) {
		return dateTime.minusMonths(months);
	}
	
	/**
	 * 获取下个月的日期
	 */
	public static DateTime nextMonth() {
		return someMonthsAfter(new DateTime(), 1);
	}
	
	/**
	 * 获取指定日期months个月之后的日期
	 * @param dateTime
	 * @param months
	 * @return
	 */
	public static DateTime someMonthsAfter(DateTime dateTime, int months) {
		return dateTime.plusMonths(months);
	}
	
	/**
	 * 获取去年的日期
	 */
	public static DateTime lastYear() {
		return someYearsAgo(new DateTime(), 1);
	}

	/**
	 * 获取指定日期n年前的日期
	 * @param dateTime
	 * @param years
	 * @return
	 */
	public static DateTime someYearsAgo(DateTime dateTime, int years) {
		return dateTime.minusYears(years);
	}
	
	/**
	 * 获取明年的日期
	 */
	public static DateTime nextYear() {
		return someYearsAfter(new DateTime(), 1);
	}
	
	/**
	 * 获取指定日期n年后的日期
	 * @param dateTime
	 * @param years
	 * @return
	 */
	public static DateTime someYearsAfter(DateTime dateTime, int years) {
		if(dateTime==null) {
			return dateTime;
		}
		return dateTime.plusYears(years);
	}
	/****************** 日期加减 end ************************/
	
	/****************** 获取特殊日期 start ************************/
	/**
	 * 获取本年最后1天的日期
	 */
	public static DateTime getLastDayOfYear() {
		return new DateTime().dayOfYear().withMaximumValue();
	}
	
	/**
	 * 获取本年第1天的日期
	 */
	public static DateTime getFirstDayOfYear() {
		return new DateTime().dayOfYear().withMinimumValue();
	}
	
	/**
	 * 获取本月最后1天的日期
	 */
	public static DateTime getLastDayOfMonth() {
		return new DateTime().dayOfMonth().withMaximumValue();
	}
	
	/**
	 * 获取本月第1天的日期
	 */
	public static DateTime getFirstDayOfMonth() {
		return new DateTime().dayOfMonth().withMinimumValue();
	}
	
	/**
	 * 获取本周的第1天的日期（中国星期规则）
	 */
	public static DateTime getFirstDayOfWeek() {
		return new DateTime().dayOfWeek().withMinimumValue();
	}
	
	/**
	 * 获取本周的最后1天（中国星期规则）
	 */
	public static DateTime getLastDayOfWeek() {
		return new DateTime().dayOfWeek().withMaximumValue();
	}
	
	/**
	 * 获取第n天后的那一周的周一的日期（中国星期规则）
	 */
	public static DateTime getFirstDayOfNDaysAfter(int n) {
		return new DateTime().plusDays(n).dayOfWeek().withMinimumValue();
	}
	
	/**
	 * 获取指定日期所在的周属于该年的第几周
	 */
	public static int getWeekOfYear(DateTime dateTime) {
		return dateTime.getWeekOfWeekyear();
	}

	/**
	 * 获取指定日期所在的月属于该年的第几月
	 */
	public static int getMonthOfYear(DateTime dateTime) {
		return dateTime.getMonthOfYear();
	}

	/**
	 * 获取上周的日期
	 * @return
	 */
	public static DateTime lastWeek() {
		return someMonthsAgo(new DateTime(), 7);
	}

	/**
	 * 获取指定日期所在周的日期列表（从周一到周日）（中国星期规则）
	 */
	public static List<String> getDateListOfWeek(DateTime dateTime){
		List<String> dateList = new ArrayList<>();
		DateTime firstDay = dateTime.dayOfWeek().withMinimumValue();
		dateList.add(dateTimeToString(firstDay, DATE_PATTERN_DEFAULT));
		dateList.add(dateTimeToString(someDaysAfter(firstDay, 1), DATE_PATTERN_DEFAULT));
		dateList.add(dateTimeToString(someDaysAfter(firstDay, 2), DATE_PATTERN_DEFAULT));
		dateList.add(dateTimeToString(someDaysAfter(firstDay, 3), DATE_PATTERN_DEFAULT));
		dateList.add(dateTimeToString(someDaysAfter(firstDay, 4), DATE_PATTERN_DEFAULT));
		dateList.add(dateTimeToString(someDaysAfter(firstDay, 5), DATE_PATTERN_DEFAULT));
		dateList.add(dateTimeToString(someDaysAfter(firstDay, 6), DATE_PATTERN_DEFAULT));
		return dateList;
	}
	
	/**
	 * 获取指定两个日期之间的所有日期列表（中国星期规则）
	 */
	public static List<String> getDateListOfTwoDate(DateTime start, DateTime end) {
		List<String> dateList = new ArrayList<>();
		// 先计算出两个日期之间相差的天数
		int daysInterval = getDaysInterval(start, end);
		dateList.add(dateTimeToString(start, DATE_PATTERN_DEFAULT));
		for (int i=1; i<=daysInterval; i++) {
			dateList.add(dateTimeToString(someDaysAfter(start, i), DATE_PATTERN_DEFAULT));
		}
		return dateList;
	}
	
	/**
	 * 获取指定两个日期之间的所有日期列表（倒序）
	 */
	public static List<String> getDateListOfTwoDateDesc(DateTime start, DateTime end) {
		List<String> dateList = new ArrayList<>();
		// 先计算出两个日期之间相差的天数
		int daysInterval = getDaysInterval(start, end);
		dateList.add(dateTimeToString(end, DATE_PATTERN_DEFAULT));
		for (int i=1; i<=daysInterval; i++) {
			dateList.add(dateTimeToString(someDaysAgo(end, i), DATE_PATTERN_DEFAULT));
		}
		return dateList;
	}

	/**
	 * 获取两个日期之间的月份列表
	 */
	public static List<String> getMonthListFromBeginYears(int beginYear) {
		List<String> resultList = new ArrayList<>();

		String today = today();
		int currYear = Integer.parseInt(today.substring(0, 4));
		int currMonth = Integer.parseInt(today.substring(5, 7));

		// 完整年份的月份列表
		List<String> monthList = new ArrayList<>(12);
		for(int i=1; i<=12; i++) {
			if(i<10) {
				monthList.add("0" + i);
			} else {
				monthList.add("" + i);
			}
		}

		// 完整年份的年-月列表
		while(beginYear < currYear) {
			for(String month : monthList) {
				resultList.add(beginYear + "-" + month);
			}
			beginYear++;
		}

		// 今年的年-月列表
		int beginMonth = 1;
		while(beginMonth <= currMonth) {
			if(beginMonth<10) {
				resultList.add(currYear + "-0" + beginMonth);
			} else {
				resultList.add(currYear + "-" + beginMonth);
			}
			beginMonth++;
		}
		return resultList;
	}

	/**
	 * 获取指定两个年份之间的所有年份列表
	 */
	public static List<String> getYearListBetweenTwoYear(String start, String end) {
		List<String> yearList = new ArrayList<>();
		yearList.add(start);
		if(start.equals(end)) {
			return yearList;
		}

		int cha = Integer.parseInt(end) - Integer.parseInt(start);
		for (int i=1; i<=cha; i++) {
			yearList.add(String.valueOf(Integer.parseInt(start) + i));
		}
		return yearList;
	}
	
	/**
	 * 获取上周日的日期
	 */
	public static DateTime lastSunday() {
		return someDaysAgo(getLastDayOfWeek(), 7);
	}
	/****************** 获取特殊日期 end ************************/

	/****************** 计算日期或时间差 start ************************/
	/**
	 * 计算两个日期相差的年份数
	 * Interval 为半开 区间，这表示由 Interval 封装的时间跨度包括这段时间的起始时刻，但是不包含结束时刻。
	 * @param start
	 * @param end
	 * @return
	 */
	public static int getYearsInterval(DateTime start, DateTime end) {
        return Years.yearsBetween(start, end).getYears();
	}
	
	/**
	 * 计算两个日期相差的月份数
	 * Interval 为半开 区间，这表示由 Interval 封装的时间跨度包括这段时间的起始时刻，但是不包含结束时刻。
	 * @param start
	 * @param end
	 * @return
	 */
	public static int getMonthsInterval(DateTime start, DateTime end) {
        return Months.monthsBetween(start, end).getMonths();
	}
	
	/**
	 * 计算两个日期相差的天数
	 * Interval 为半开 区间，这表示由 Interval 封装的时间跨度包括这段时间的起始时刻，但是不包含结束时刻。
	 * @param start
	 * @param end
	 * @return
	 */
	public static int getDaysInterval(DateTime start, DateTime end) {
		return Days.daysBetween(start, end).getDays();
	}
	
	/**
	 * 获取两个日期相差的毫秒数
	 * Duration：表示一个绝对的精确跨度，单位:毫秒。
	 * @param start
	 * @param end
	 * @return
	 */
	public static long getMillsInterval(DateTime start, DateTime end) {
		Duration d = new Duration(start, end);
		return d.getMillis();
	}
	
	/**
	 * 获取两个日期相差的秒数
	 * @param start
	 * @param end
	 * @return
	 */
	public static long getSecondsInterval(DateTime start, DateTime end) {
		Duration d = new Duration(start, end);
		return d.getMillis() / 1000;
	}
	
	/**
	 * 获取今天剩余的秒数
	 * 
	 */
	public static long getRemaindSecondsToTodayEnd() {
		DateTime start = now();
//		DateTime end = new DateTime(today() + "T23:59:59"); // 第1种办法
		DateTime end = start.dayOfWeek().roundCeilingCopy();// 第2种办法
		return getSecondsInterval(start, end);
	}
	/****************** 计算日期或时间差 end ************************/

	/****************** 日期比较 start ************************/
	/**
	 * start是否在end之前
	 * @param start
	 * @param end
	 * @return
	 */
	public static boolean isBefore(DateTime start, DateTime end) {
		return start.isBefore(end);
	}
	
	/**
	 * start是否在end之后
	 * @param start
	 * @param end
	 * @return
	 */
	public static boolean isAfter(DateTime start, DateTime end) {
		return start.isAfter(end);
	}
	
	/**
	 * dateTime 是否早于当前时间
	 */
	public static boolean isBeforeNow(DateTime dateTime) {
		return dateTime.isBeforeNow();
	}
	
	/**
	 * dateTime 是否晚于当前时间
	 */
	public static boolean isAfterNow(DateTime dateTime) {
		return dateTime.isAfterNow();
	}
	
	/**
	 * dateTime 是否等于当前时间
	 */
	public static boolean isEqualNow(DateTime dateTime) {
		return dateTime.isEqualNow();
	}
	
	/**
	 * 是否为闰年
	 */
	public static boolean isLeapYear(DateTime dateTime) {
		return dateTime.year().isLeap();
	}
	
	/**
	 * startDate是否在endDate之前
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static boolean isBefore(String startDate, String endDate) {
		return isBefore(
				JodaUtil.stringToDateTime(startDate, JodaUtil.DATE_PATTERN_DEFAULT), 
				JodaUtil.stringToDateTime(startDate, JodaUtil.DATE_PATTERN_DEFAULT)
			);
	}
	
	/**
	 * startDate是否在endDate之后
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static boolean isAfter(String startDate, String endDate) {
		return isAfter(
				JodaUtil.stringToDateTime(startDate, JodaUtil.DATE_PATTERN_DEFAULT), 
				JodaUtil.stringToDateTime(startDate, JodaUtil.DATE_PATTERN_DEFAULT)
			);
	}
	
	/**
	 * startDate是否在今天之前
	 * @param strDate
	 * @return
	 */
	public static boolean isBeforeNow(String strDate) {
		return isBeforeNow(JodaUtil.stringToDateTime(strDate, JodaUtil.DATE_PATTERN_DEFAULT));
	}
	
	/**
	 * startDate是否在今天之后
	 * @param strDate
	 * @return
	 */
	public static boolean isAfterNow(String strDate) {
		return isAfterNow(JodaUtil.stringToDateTime(strDate, JodaUtil.DATE_PATTERN_DEFAULT));
	}

	/**
	 * 判断当前时间是否在指定时间范围之内
	 * @param start
	 * @param end
	 * @return
	 */
	public static boolean isWithin(DateTime start, DateTime end) {
		return isBeforeNow(start) && isAfterNow(end);
	}
	/****************** 日期比较 end ************************/
	
	/****************** 日期转换为字符串 start ************************/
	/**
	 * 默认格式化
	 * @param dateTime
	 * @return
	 */
	public static String dateTimeToString(DateTime dateTime) {
		return dateTimeToString(dateTime, DATETIME_PATTERN_DEFAULT);
	}
	
	/**
	 * 日期格式化输出
	 * @param dateTime
	 * @param pattern
	 * @return
	 */
	public static String dateTimeToString(DateTime dateTime, String pattern) {
		if(dateTime==null){
			return null;
		}
		return dateTime.toString(pattern);
	}
	
	/**
	 * 获取今天的日期字符串
	 */
	public static String today() {
		return dateTimeToString(now(), DATE_PATTERN_DEFAULT);
	}
	
	/**
	 * 获取今天的日期字符串
	 */
	public static String today(String pattern) {
		return dateTimeToString(now(), pattern);
	}
	
	/**
	 * 获取当前时间字符串
	 */
	public static String currentTime() {
		return dateTimeToString(now(), DATETIME_PATTERN_DEFAULT);
	}
	
	/**
	 * 获取当月的日期字符串
	 */
	public static String currentMonth() {
		String today = today(DATE_PATTERN_DEFAULT);
		return today.substring(0, 7);
	}

	/**
	 * 获取当前季度的日期字符串
	 * return 格式：YYYY-J
	 */
	public static String currentQuarter() {
		String quarter = "";
		
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH) + 1; // 老外月份是0~11月
		if (month >= 1 && month <= 3) {
			quarter = "1";
		} else if (month >= 4 && month <= 6) {
			quarter = "2";
		} else if (month >= 7 && month <= 9) {
			quarter = "3";
		} else if (month >= 10 && month <= 12) {
			quarter = "4";
		}

		return year + "-" + quarter;
	}
	
	/**
	 * 获取当年的日期字符串
	 */
	public static String currentYear() {
		String today = today(DATE_PATTERN_DEFAULT);
		return today.substring(0, 4);
	}

	/**
	 * 获取去年的日期字符串
	 */
	public static String getLastYear() {
		DateTime dt = lastYear();
		return dateTimeToString(dt, DATE_PATTERN_DEFAULT).substring(0, 4);
	}

	/****************** 日期转换为字符串 end ************************/

	/****************** 字符串转换为日期 start ************************/
	/**
	 * 将字符串转换为日期对象
	 * @param jodaTime：格式：yyyy-MM-ddThh:mm:ss
	 * @return
	 */
	public static DateTime stringToDateTime(String jodaTime) {
		return new DateTime(jodaTime);
	}
	
	/**
	 * 将指定格式的JDK时间字符串转换为Joda日期对象
	 * @param jdkTime
	 * @return
	 */
	public static DateTime stringToDateTime(String jdkTime, String pattern) {
		Date date = null;
		try {
			date = (new SimpleDateFormat(pattern)).parse(jdkTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		if (date != null) {
			return new DateTime(date);
		} else {
			return null;
		}
	}
	
	/**
	 * 将Joda日期对象转换为指定格式的JDK日期时间
	 * @param dateTime
	 * @return
	 */
	public static Date dateTimeToJdkTime(DateTime dateTime) {
		Date date = null;
		try {
			String jdkTime = dateTimeToString(dateTime);
			date = (new SimpleDateFormat(DATETIME_PATTERN_DEFAULT)).parse(jdkTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date;
	}
	/****************** 字符串转换为日期 end ************************/
	
	/**
     * Java将Unix时间戳转换成指定格式日期字符串
     * @param unixTimeSecond unix时间戳（秒） 如："1473048265";
     * @param pattern 要格式化的格式 默认："yyyy-MM-dd HH:mm:ss";
     *
     * @return 返回结果 如："2016-09-05 16:06:42";
     */
    public static String TimeStamp2Date(Long unixTimeSecond, String pattern) {
        return new SimpleDateFormat(pattern, Locale.CHINA).format(new Date(unixTimeSecond * 1000));
    }
    
    /**
     * 获取系统启动时间戳，作为静态资源版本号，格式：yyyyMMddHHmm
     */
    public static String getVersionNo() {
        return new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
    }
    
    /**
     * 判断今天是否过了12点
     * @return
     */
	public static boolean isAfter12() {
		String time12 = today() + " 12:00:00";
		DateTime time12Date = stringToDateTime(time12, DATETIME_PATTERN_DEFAULT);
		return isBeforeNow(time12Date);
	}

    /**
     * 判断今天是否为周日
     * @return
     */
	public static boolean isSundayToday() {
		DateTime sundayDate = getLastDayOfWeek();
		String sundayStr = dateTimeToString(sundayDate, DATE_PATTERN_DEFAULT);
		String today = today(DATE_PATTERN_DEFAULT);
		return sundayStr.equals(today);
	}
	
	/**
	 * 判断是否为大额逆镜像时间段
	 */
	public static boolean isBigInverselyTime() {
		if(isSundayToday() && isAfterNoon()) { // 周日 && 下午
			return true;
		}
		return false;
	}
	
    /**
     * 判断当前时刻是否为下午
     * @return
     */
	public static boolean isAfterNoon() {
		DateTime now = now();
		int hour = now.getHourOfDay();
		if(hour>=12 && hour<18) { // [12, 18)
			return true;
		}
		return false;
	}
	
    /**
     * 判断当前时刻是否为正午
     * @return
     */
	public static boolean isMidNoon() {
		DateTime now = now();
		int hour = now.getHourOfDay();
		if(hour>11 && hour<13) {
			return true;
		}
		return false;
	}
	
    /**
     * 判断当前时刻是否为深夜
     * @return
     */
	public static boolean isMidNight() {
		DateTime now = now();
		int hour = now.getHourOfDay();
		if(hour>23 || hour<6) {
			return true;
		}
		return false;
	}
	
	/**
	 * 判断年份是否合法
	 */
	public static boolean isYear(String year, String pattern) {
		try {
			String date = year + "-01-01";
    		DateTime dateTime = JodaUtil.stringToDateTime(date, pattern);
    		if(dateTime!=null) {
    			return true;
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 判断月份是否合法
	 */
	public static boolean isYM(String ym, String pattern) {
		try {
			String date = ym + "-01";
    		DateTime dateTime = JodaUtil.stringToDateTime(date, pattern);
    		if(dateTime!=null) {
    			return true;
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 判断日期是否合法
	 */
	public static boolean isYMD(String ymd, String pattern) {
		try {
    		DateTime dateTime = JodaUtil.stringToDateTime(ymd, pattern);
    		if(dateTime!=null) {
    			return true;
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 判断季度是否合法
	 */
	public static boolean isQuarter(String yq, String pattern) {
		try {
			String[] arr = yq.split("-");
    		String year = arr[0];
    		String quarter = arr[1];
    		if(!isYear(year, pattern)) {
    			return false;
    		}
    		if(!("1".equals(quarter)
    			|| "2".equals(quarter)
    			|| "3".equals(quarter)
    			|| "4".equals(quarter))) {
    			return false;
    		}
    		return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 判断日期是否合法
	 */
	public static boolean isYMDHMS(String ymdhms, String pattern) {
		try {
    		DateTime dateTime = JodaUtil.stringToDateTime(ymdhms, pattern);
    		if(dateTime!=null) {
    			return true;
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 获取指定日期所在季度
	 * @param date 日期，默认为当天
	 * return 格式：YYYYJ
	 */
	public static String getQuarterOfYear(Date date) {
		String quarter = "";
		
		// 如果传入日期为空，则为当前日期
		if(date==null) {
			date = new Date();
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH) + 1; // 老外月份是0~11月
		if (month >= 1 && month <= 3) {
			quarter = "1";
		} else if (month >= 4 && month <= 6) {
			quarter = "2";
		} else if (month >= 7 && month <= 9) {
			quarter = "3";
		} else if (month >= 10 && month <= 12) {
			quarter = "4";
		}

		return year + quarter;
	}
	
	/**
	 * 获取指定季度的下一个季度
	 * @param lastFeeQuarter YYYYJ
	 * @return
	 */
	public static String nextQuarter(String lastFeeQuarter) {
		String year = lastFeeQuarter.substring(0, 4);
		String quarter = lastFeeQuarter.substring(4, 5);
		
		if("1".equals(quarter)) {
			quarter = "2";
		} else if("2".equals(quarter)) {
			quarter = "3";
		} else if("3".equals(quarter)) {
			quarter = "4";
		} else if("4".equals(quarter)) {
			quarter = "1";
			year = String.valueOf(Integer.valueOf(year) + 1);
		}
		
		return year + quarter;
	}

	/**
	 * 获取上一季度的日期字符串
	 * return 格式：YYYY-J
	 */
	public static String lastQuarter() {
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		int presentQuarter = (month / 3) + 1;
		int lastQuarter = (presentQuarter - 1) > 0 ? presentQuarter - 1 : 4;
		if(lastQuarter==4) { // 如果季度是4，则年份-1
			year = year - 1;
		}
		return year + "-" + lastQuarter;
	}

	/**
	 * 根据DateTime获取该年第几周
	 * 格式：YYYY-WW
	 */
	public static String getYearWeek(DateTime dt) {
		String result = "";

		if(dt==null) {
			dt = new DateTime();
		}
		String thisYear = JodaUtil.dateTimeToString(dt).substring(0, 4);
		int weekOfYear = dt.getWeekOfWeekyear();
		if(weekOfYear<10) {
			result = thisYear + "-0" + weekOfYear;
		} else {
			result = thisYear + "-" + weekOfYear;
		}
		return result;
	}

	/**
	 * 根据DateTime获取该年第几月
	 * 格式：YYYY-MM
	 */
	public static String getYearMonth(DateTime dt) {
		String result = "";

		if(dt==null) {
			dt = new DateTime();
		}
		String thisYear = JodaUtil.dateTimeToString(dt).substring(0, 4);
		int monthOfYear = dt.getMonthOfYear();
		if(monthOfYear<10) {
			result = thisYear + "-0" + monthOfYear;
		} else {
			result = thisYear + "-" + monthOfYear;
		}
		return result;
	}

	/**
	 * 通过weekofYear获取本周第一天日期
	 * eg：2022-27所在周的第一天是2022-07-04
	 */
	public static String getFirstDayByWeekOfYear(String yyyyWW) {
		String year = yyyyWW.split("-")[0];
		String week = yyyyWW.split("-")[1];
		if(week.startsWith("0")){
			week = week.substring(1);
		}
		int weeksOfYear = Integer.parseInt(week);
		String time = year + "-01-01 00:00:00"; // 2022-01-01 00:00:00
		DateTime dateTime = stringToDateTime(time, DATETIME_PATTERN_DEFAULT);
		DateTime firstDayOfYear = dateTime.dayOfYear().withMinimumValue();
		DateTime minDateOfWeek = firstDayOfYear.dayOfWeek().withMinimumValue(); // 周最后一天
		DateTime theWeekDateTime = minDateOfWeek.plusWeeks(weeksOfYear);
		String result = dateTimeToString(theWeekDateTime);
		return result.substring(0, 10);
	}

	/**
	 * 通过weekofYear获取本周最后一天日期
	 * eg：2022-26所在周的最后一天是2022-07-03
	 */
	public static String getLastDayByWeekOfYear(String yyyyWW) {
		String year = yyyyWW.split("-")[0];
		String week = yyyyWW.split("-")[1];
		if(week.startsWith("0")){
			week = week.substring(1);
		}
		int weeksOfYear = Integer.parseInt(week);
		String time = year + "-01-01 00:00:00"; // 2022-01-01 00:00:00
		DateTime dateTime = stringToDateTime(time, DATETIME_PATTERN_DEFAULT);
		DateTime firstDayOfYear = dateTime.dayOfYear().withMinimumValue();
		DateTime maxDateOfWeek = firstDayOfYear.dayOfWeek().withMaximumValue(); // 周最后一天
		DateTime theWeekDateTime = maxDateOfWeek.plusWeeks(weeksOfYear);
		String result = dateTimeToString(theWeekDateTime);
		return result.substring(0, 10);
	}

	/**
	 * 通过monthofYear获取本月第一天日期
	 * eg：2022-06所在月的最后一天是2022-06-01
	 */
	public static String getFirstDayByMonthOfYear(String yyyyMM) {
		String year = yyyyMM.split("-")[0];
		String month = yyyyMM.split("-")[1];
		if(month.startsWith("0")){
			month = month.substring(1);
		}
		int monthsOfYear = Integer.parseInt(month);
		String time = year + "-01-01 00:00:00"; // 2022-01-01 00:00:00
		DateTime dateTime = stringToDateTime(time, DATETIME_PATTERN_DEFAULT);
		DateTime firstDayOfYear = dateTime.dayOfYear().withMinimumValue();
		DateTime maxDateOfMonth = firstDayOfYear.dayOfMonth().withMinimumValue(); // 月最后一天
		DateTime theMonthDateTime = maxDateOfMonth.plusMonths(monthsOfYear-1);
		String result = dateTimeToString(theMonthDateTime);
		return result.substring(0, 10);
	}

	/**
	 * 通过monthofYear获取本月最后一天日期
	 * eg：2022-06所在月的最后一天是2022-06-30
	 */
	public static String getLastDayByMonthOfYear(String yyyyMM) {
		String year = yyyyMM.split("-")[0];
		String month = yyyyMM.split("-")[1];
		if(month.startsWith("0")){
			month = month.substring(1);
		}
		int monthsOfYear = Integer.parseInt(month);
		String time = year + "-01-01 00:00:00"; // 2022-01-01 00:00:00
		DateTime dateTime = stringToDateTime(time, DATETIME_PATTERN_DEFAULT);
		DateTime firstDayOfYear = dateTime.dayOfYear().withMinimumValue();
		DateTime maxDateOfMonth = firstDayOfYear.dayOfMonth().withMaximumValue(); // 月最后一天
		DateTime theMonthDateTime = maxDateOfMonth.plusMonths(monthsOfYear-1);
		String result = dateTimeToString(theMonthDateTime);
		return result.substring(0, 10);
	}

	/**
	 * 获取指定日期所在的周
	 * eg：2022-07-03所在周为2022-26
	 */
	public static String getYearWeekByDate(String yyyyMMdd) {
		DateTime dt = stringToDateTime(yyyyMMdd, DATE_PATTERN_DEFAULT);
		int weekOfYear = dt.getWeekOfWeekyear();
		String thisYear = yyyyMMdd.substring(0, 4);
		String result = "";
		if(weekOfYear<10) {
			result = thisYear + "-0" + weekOfYear;
		} else {
			result = thisYear + "-" + weekOfYear;
		}
		return result;
	}

	/**
	 * 获取指定日期所在的月
	 * eg：2022-07-03所在周为2022-07
	 */
	public static String getYearMonthByDate(String yyyyMMdd) {
		DateTime dt = stringToDateTime(yyyyMMdd, DATE_PATTERN_DEFAULT);
		String thisYear = yyyyMMdd.substring(0, 4);
		String result = "";
		int monthOfYear = dt.getMonthOfYear();
		if(monthOfYear<10) {
			result = thisYear + "-0" + monthOfYear;
		} else {
			result = thisYear + "-" + monthOfYear;
		}
		return result;
	}

	/**
	 * ISO格式转DateTime
	 */
	public static DateTime iso2DateTime(String isoDateTime) {
		DateTime dateTime = new DateTime(Instant.parse(isoDateTime)) ;
		return dateTime;
	}

	/**
	 * ISO格式转Unix时间戳
	 */
	public static Long iso2UnixTimestamp(String isoDateTime) {
		DateTime dateTime = new DateTime(Instant.parse(isoDateTime)) ;
		Date jdkDateTime = dateTimeToJdkTime(dateTime);
		return jdkDateTime.getTime();
	}

	/**
	 * ISO格式转Unix时间戳（北京时间）
	 */
	public static Long iso2UnixTimestamp4BJT(String isoDateTime) {
		DateTime dateTime = new DateTime(Instant.parse(isoDateTime)) ;
		Date jdkDateTime = dateTimeToJdkTime(dateTime);
		return jdkDateTime.getTime()+1000*3600*8;
	}
    
	/**
	 * main
	 */
	public static void main(String[] args) {
		DateTime now = JodaUtil.now();
//		System.out.println("now: " + now);
//		System.out.println("currentTime:" + JodaUtil.currentTime());
//		System.out.println("today: " + JodaUtil.today());
//		System.out.println("yesterday: " +JodaUtil.dateTimeToString(JodaUtil.yesterday()));
//		System.out.println("9000 seconds after:" + JodaUtil.someSecondsAfter(now, 9000));
//		System.out.println("3600 seconds before:" + JodaUtil.dateTimeToString(JodaUtil.someSecondsBefore(JodaUtil.now(), 3600)));
//		System.out.println("stringToDateTime: " + JodaUtil.stringToDateTime("2018-06-19 17:09:10", DATETIME_PATTERN_DEFAULT));
//		System.out.println(JodaUtil.stringToDateTime("2023-07-20T10:12:30"));
//		System.out.println("weekOfYear: " + JodaUtil.getWeekOfYear(now));
//		System.out.println("monthOfYear: " + JodaUtil.getMonthOfYear(now));
//		System.out.println("remaindSecondsToTodayEnd: " + JodaUtil.getRemaindSecondsToTodayEnd());
//		System.out.println("isLeapYear: " + JodaUtil.isLeapYear(now));
//		List<String> dateList = getDateListOfWeek(now);
//		System.out.println("dateList of now: ");
//		for(String str : dateList) {
//			System.out.println(str);
//		}
//		List<String> dateList1 = getDateListOfTwoDate(now, new DateTime("2022-10-21T10:00:01"));
//		System.out.println("dateList1 between two date: ");
//		for(String str : dateList1) {
//			System.out.println(str);
//		}
//		System.out.println("getDaysInterval:" + getDaysInterval(new DateTime("2018-09-16T20:00:01"), now));
//		System.out.println("getMonthsInterval:" + getMonthsInterval(new DateTime("2018-07-16T20:00:01"), now));
//		System.out.println("getYearsInterval:" + getYearsInterval(new DateTime("2017-09-18T20:00:01"), now));
//
//		DateTime start = JodaUtil.stringToDateTime("2018-09-01", JodaUtil.DATE_PATTERN_DEFAULT);
//        int daysInterval = JodaUtil.getDaysInterval(start, JodaUtil.now());
//        System.out.println("daysInterval:" + daysInterval);
//        System.out.println("versionNo:" + getVersionNo());
//        System.out.println("isAfter12:" + isAfter12());
//        System.out.println("isSundayToday:" + isSundayToday());
//        System.out.println(JodaUtil.today(JodaUtil.DATETIME_PATTERN_YYYYMMDDHHMMSS));
//        System.out.println(dateTimeToJdkTime(new DateTime("2019-10-01T10:00:01")));
//        System.out.println(get0OclockOfToday());
//
//        System.out.println(getQuarterOfYear(null));
//        System.out.println(nextQuarter("20204"));
//        System.out.println(nextQuarter("20211"));
//
//        System.out.println(currentMonth());
//        System.out.println(currentQuarter());
//        System.out.println(currentYear());
//        System.out.println(lastMonth());
//        System.out.println(lastQuarter());
//        System.out.println(lastYear());

//		System.out.println(iso2DateTime("2022-06-22T06:16:41.000Z"));
//		System.out.println(iso2UnixTimestamp("2022-06-22T06:16:41.000Z"));
//		System.out.println(iso2UnixTimestamp4BJT("2022-06-22T06:16:41.000Z"));

//		System.out.println(getFirstDayByWeekOfYear("2022-01"));
//		System.out.println(getFirstDayByWeekOfYear("2022-02"));
//		System.out.println(getFirstDayByWeekOfYear("2022-24"));
//		System.out.println(getFirstDayByWeekOfYear("2022-25"));
//		System.out.println(getFirstDayByWeekOfYear("2022-26"));
//		System.out.println(getFirstDayByWeekOfYear("2022-27"));
//		System.out.println(getFirstDayByMonthOfYear("2022-01"));
//		System.out.println(getFirstDayByMonthOfYear("2022-02"));
//		System.out.println(getFirstDayByMonthOfYear("2022-03"));
//		System.out.println(getFirstDayByMonthOfYear("2022-04"));
//		System.out.println(getFirstDayByMonthOfYear("2022-05"));
//		System.out.println(getFirstDayByMonthOfYear("2022-06"));
//		System.out.println(getFirstDayByMonthOfYear("2022-07"));

//		System.out.println(getYearWeekByDate("2022-06-01"));
//		System.out.println(getYearWeekByDate("2022-07-03"));
//		System.out.println(getYearWeekByDate("2022-07-04"));
//		System.out.println(getYearMonthByDate("2022-06-01"));
//		System.out.println(getYearMonthByDate("2022-07-03"));
//		System.out.println(getYearMonthByDate("2022-07-04"));

//		System.out.println(someYearsAgo(now, 1));
//		System.out.println(someYearsAgo(now, 3));
//		System.out.println(someYearsAgo(now, -1));

//		System.out.println(getMonthListFromBeginYears(2013));
//		System.out.println(addHyphen("201203"));

//		System.out.println(getLastQuarterDateByDate("2023-06-14"));
//		System.out.println(getLastQuarterDateByDate("2023-02-14"));
//		System.out.println(getLastQuarterDateByDate("2022-12-14"));
//		System.out.println(getLastQuarterDateByDate("2022-08-14"));
//		System.out.println(getLastQuarterDateByDate("2022-03-31"));

//		System.out.println(isWithin(
//				JodaUtil.stringToDateTime("2023-07-20 09:30:00", DATETIME_PATTERN_DEFAULT),
//				JodaUtil.stringToDateTime("2023-07-20 11:30:00", DATETIME_PATTERN_DEFAULT)));

		System.out.println(getYearListBetweenTwoYear("2020", "2022"));

//		System.out.println(getYearQuarterByDate("2023-04-10"));
//		System.out.println(getQuarterDateByDate("2023-07-10"));

//		Long someDaysAgo = JodaUtil.someDaysAgo(JodaUtil.now(), 30).getMillis();
//		System.out.println(someDaysAgo);
	}
	
}
